/*
 *  shnode.h
 *  shaderz_v3
 *
 *  Created by Anjali on 3/23/11.
 *  Copyright 2011 __MyCompanyName__. All rights reserved.
 *
 */

#ifndef __SH_NODE_H__
#define __SH_NODE_H__

// stl headers
#include <string>
#include <vector>
#include <list>

// shaderz headers
#include "shobject.h"

#include <iostream>
namespace shaderz
{
	class shNode : public shObject
	{
	public:
		typedef std::list<shNode*>::iterator	iterator;
	
		enum linkStubType { SHST_CONST1VEC=0, 
							SHST_CONST2VEC,
							SHST_CONST3VEC,
							SHST_CONST4VEC,
							SHST_TEXTURE,
							SHST_COLOR = SHST_CONST4VEC,
							SHST_RGBA = SHST_COLOR,
							SHST_RGB = SHST_CONST3VEC,
							SHST_RED = SHST_CONST1VEC,
							SHST_BLUE = SHST_CONST1VEC,
							SHST_GREEN = SHST_CONST1VEC,
							SHST_ALPHA = SHST_CONST1VEC,
						  };
						  
		enum linkIOType { SHIO_INPUT=0, SHIO_OUTPUT };
		
		// the link definition from this node to otherNode, and what stub its connected to
		struct link
		{
			shNode*		otherNode;
			std::string	otherStubName;
		};
	
		// link stub which is capable of originating a connection to other node stubs
		struct linkStub
		{
			// note to self: initially started off as a union; but had to move back to strut coz of a malloc() error 
			// causing the allocated memory to be curropted.
			struct _ValueCache
			{
				float		constant1Vec;
				float		constant2Vec[2];
				float		constant3Vec[3];
				float		constant4Vec[4];
				// something for texture
			};
		
			_ValueCache			value;
			linkIOType			ioType;
			std::string			name;
			linkStubType		type;
			std::vector<link>	allLinks;
			
			linkStub()
				: ioType( SHIO_INPUT )
				, name("DefaultName")
				, type( SHST_CONST1VEC )
			{
				clear();
			}
			
			linkStub( const linkStub& InRhs )
			{
				std::cout<<"Invoking copy constructor: RHS.const1Vec = "<<InRhs.value.constant1Vec<<std::endl;
				value = InRhs.value;
				ioType = InRhs.ioType;
				name = InRhs.name;
				type = InRhs.type;
				allLinks = InRhs.allLinks;
			}
						
			linkStub& operator +( const linkStub& InRhs );
			linkStub& operator -( const linkStub& InRhs );
			linkStub& operator *( const linkStub& InRhs );
			linkStub& operator /( const linkStub& InRhs );
			linkStub& operator =( const linkStub& InRhs );
			
			// clears the value part of this stub
			void clear();
						
			// converts the stub into a string
			std::string toString() const;
		};
			
	public:
		shNode();
		shNode( const std::string& InNodeName );
		virtual ~shNode();

		// iterator interface
		iterator	firstNode() { return mAllNodes.begin(); }
		iterator	lastNode() { return mAllNodes.end(); }
		
		// misc helper functions
		static linkStub* constructLinkStub( const std::string& InLinkName = "DefaultName"
											, linkIOType   InIOType = SHIO_INPUT
											, linkStubType InType = SHST_CONST1VEC );
		
		// getters
		const std::string& name() const { return mNodeName; }
		std::string&	name()  { return mNodeName; }
		const linkStub* findStub( std::string InStubName )const;
		linkStub*		findStub( std::string InStubName );
		std::vector<linkStub*>& inputStubs() { return mInputStubs; }
		std::vector<linkStub*>& outputStubs()  { return mOutputStubs; }
		
		virtual bool areStubsCompatible( linkStubType InType1, linkStubType InType2 );
		virtual bool isUpcastingPossible( linkStubType InType1, linkStubType InType2 );
		
		// setters
		virtual void addInputStub( linkStub* InNewStub );
		virtual void addOutputStub( linkStub* InNewStub );
		virtual bool connect( std::string InStubNameToConnect, shNode* InOtherNode, std::string InOtherStubName );
		virtual void disconnectFrom( shNode* InOtherNode, std::string InStubName="" );
		
		virtual void rename( std::string InNewNodeName );
		virtual void renameStub( std::string InOldStubName, std::string InNewStubName );
		
		// operation functions
		virtual void evaluate();
		
		// debug helpers
#ifdef SH_DEBUG
public:
		virtual void dumpNodeStats() const;
#endif
	
	protected:	
		std::string					mNodeName;
		std::vector<linkStub*>		mInputStubs;
		std::vector<linkStub*>		mOutputStubs;
	
		// tracking all created nodes	
		static std::list<shNode*> mAllNodes;
	
	private:
		typedef shNode	ParentClass;
	};
}

#endif
